import { IPEndPoint } from "./IPEndPoint";

const MaxValue = 2147483647;
const UintMaxValue = 4294967295;
export enum ServiceType {
    Outer,
    Inner,
}
export abstract class AService {
    public ServiceType = ServiceType.Outer;
    private connectIdGenerater = Long.fromInt(MaxValue);
    public CreateConnectChannelId(localConn: number): Long {
        this.connectIdGenerater = this.connectIdGenerater.sub(1);
        return this.connectIdGenerater.shiftLeft(32).or(localConn);;
    }
    public CreateRandomLocalConn(): number {
        return (1 << 30) | et.math.randomNumber(0, UintMaxValue);
    }
    private acceptIdGenerater = Long.fromValue(1);
    public CreateAcceptChannelId(localConn: number) {
        this.acceptIdGenerater = this.acceptIdGenerater.add(1);
        return this.acceptIdGenerater.shiftLeft(32).or(localConn);
    }
    public abstract Update(): void;

    public abstract Remove(id: Long): void;

    public abstract IsDispose(): boolean;

    protected abstract Get(id: Long, address: IPEndPoint): void;

    public abstract Dispose(): void;

    protected abstract Send(channelId: Long, actorId: Long, stream: DataView): void;

    protected OnAccept(channelId: Long, ipEndPoint: IPEndPoint) {
        this.AcceptCallback.Invoke(channelId, ipEndPoint);
    }
    public OnRead(channelId: Long, memoryStream: DataView) {
        this.ReadCallback.Invoke(channelId, memoryStream);
    }
    public OnError(channelId: Long, e: number) {
        this.Remove(channelId);
        this.ErrorCallback?.Invoke(channelId, e);
    }
    public AcceptCallback = new et.Action2<Long, IPEndPoint>();
    public ErrorCallback = new et.Action2<Long, number>();
    public ReadCallback = new et.Action2<Long, DataView>();
    public Destroy(): void {
        this.Dispose();
    }
    public RemoveChannel(channelId: Long) {
        this.Remove(channelId);

    }
    public SendStream(channelId: Long, actorId: Long, stream: DataView) {
        this.Send(channelId, actorId, stream);
    }
    public GetOrCreate(id: Long, address: IPEndPoint) {
        this.Get(id, address);
    }
}